<template>
  <view class="waterfalls-flow">
    <view
      v-for="(item, index) in data.column"
      :key="index"
      class="waterfalls-flow-column"
      :id="`waterfalls_flow_column_${index + 1}`"
      :msg="msg"
      :style="{ width: w, 'margin-left': index == 0 ? 0 : m }"
    >
      <view
        :class="['column-value', { 'column-value-show': item2.o }]"
        v-for="(item2, index2) in columnValue(index)"
        :key="index2"
        :style="[s1]"
        @click.stop="itemClick(item2)"
      >
        <view class="inner" v-if="data.seat == 1">
          <!-- #ifdef MP-WEIXIN -->
          <!-- #ifdef VUE2 -->
          <slot name="slot{{item2.index}}"></slot>
          <!-- #endif -->
          <!-- #ifdef VUE3 -->
          <slot :name="`slot${item2.index}`"></slot>
          <!-- #endif -->
          <!-- #endif -->
          <!-- #ifndef MP-WEIXIN -->
          <slot v-bind="item2"></slot>
          <!-- #endif -->
        </view>
        <image
          :class="[
            'img',
            {
              'img-hide':
                item2[hideImageKey] == true || item2[hideImageKey] == 1,
            },
            { 'img-error': !item2[data.imageKey] },
          ]"
          :src="item2[data.imageKey]"
          mode="widthFix"
          @load="imgLoad(item2, index + 1)"
          @error="imgError(item2, index + 1)"
          @tap.stop="imageClick(item2)"
          @touchstart="handleRecordStart"
          @touchend="handleRecordEnd"
          @longpress="handleLongTap(index,index2)"
        ></image>
        <view class="inner" v-if="data.seat == 2">
          <!-- #ifdef MP-WEIXIN -->
          <!-- #ifdef VUE2 -->
          <slot name="slot{{item2.index}}"></slot>
          <!-- #endif -->
          <!-- #ifdef VUE3 -->
          <slot :name="`slot${item2.index}`"></slot>
          <!-- #endif -->
          <!-- #endif -->
          <!-- #ifndef MP-WEIXIN -->
          <slot v-bind="item2"></slot>
          <!-- #endif -->
        </view>
        <!-- 删除 -->
        <view
          v-if="existDel && recordDelId === `${index}-${index2}` && recordDelType"
          class="mask"
          @longpress="handleLongTap(index,index2)"
        >
          <view
            class="mask__text"
            @tap.stop="handleDel(item2)"
            @touchstart="handleRecordStart"
            @touchend="handleRecordEnd"
            >删除</view
          >
        </view>
        <!-- 下架原因 -->
        <view v-if="item2[failKey]" class="mask">
          <view class="mask__tip">{{ item2[failKey] }}</view>
        </view>
      </view>
    </view>
  </view>
</template>
<script>
export default {
  props: {
    value: Array,
    column: {
      // 列的数量
      type: [String, Number],
      default: 2,
    },
    maxColumn: {
      // 最大列数
      type: [String, Number],
      default: 5,
    },
    columnSpace: {
      // 列之间的间距 百分比
      type: [String, Number],
      default: 2,
    },
    imageKey: {
      // 图片key
      type: [String],
      default: "image",
    },
    hideImageKey: {
      // 隐藏图片key
      type: [String],
      default: "hide",
    },
    seat: {
      // 文本的位置，1图片之上 2图片之下
      type: [String, Number],
      default: 2,
    },
    listStyle: {
      // 单个展示项的样式：eg:{'background':'red'}
      type: Object,
    },
    existDel: {
      type: Boolean,
      default: false,
    },
    failKey: {
      type: String,
      default: "reason",
    },
  },
  data() {
    return {
      data: {
        list: this.value ? this.value : [],
        column: this.column < 2 ? 2 : this.column,
        columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
        imageKey: this.imageKey,
        seat: this.seat,
      },
      msg: 0,
      listInitStyle: {
        "border-radius": "12rpx",
        "margin-bottom": "20rpx",
        "background-color": "#fff",
      },
      adds: [], //预置数据
      isLoaded: true,
      curIndex: 0,
      isRefresh: true,
      flag: false,
      refreshDatas: [],
      recordDelId: "",
      recordDelType: false,
      touchStart: 0,
      touchEnd: 0,
    };
  },
  computed: {
    // 计算列宽
    w() {
      const column_rate = `${100 / this.data.column - +this.data.columnSpace}%`;
      return column_rate;
    },
    // 计算margin
    m() {
      const column_margin = `${
        (100 -
          (100 / this.data.column - +this.data.columnSpace).toFixed(5) *
            this.data.column) /
        (this.data.column - 1)
      }%`;
      return column_margin;
    },
    // list样式
    s1() {
      return { ...this.listInitStyle, ...this.listStyle };
    },
  },
  created() {
    // 初始化
    this.refresh();
  },
  methods: {
    handleLongTap(parentIndex,curIndex) {
      if (!this.existDel) return;
      if (this.recordDelId === `${parentIndex}-${curIndex}` && this.recordDelType) {
        this.recordDelType = false;
        this.recordDelId = "";
      } else {
        this.recordDelType = true;
        this.recordDelId = `${parentIndex}-${curIndex}`;
      }
    },
    handleRecordStart() {
      this.touchStart = new Date().getTime();
    },
    handleRecordEnd() {
      this.touchEnd = new Date().getTime();
    },
    handleDel(e) {
      if (this.touchEnd - this.touchStart < 200) {
        this.$emit("itemDel", e);
        this.recordDelId=''
      }
    },
    // 预加载图片
    loadImages(idx = 0) {
      let count = 0;
      const newList = this.data.list.filter((item, index) => index >= idx);
      for (let i = 0; i < newList.length; i++) {
        // #ifndef APP-PLUS
        uni.getImageInfo({
          src: `${newList[i][this.imageKey]}.jpg`,
          complete: (res) => {
            count++;
            if (count == newList.length) this.initValue(idx);
          },
        });
        // #endif
        // #ifdef APP-PLUS
        plus.io.getImageInfo({
          src: `${newList[i][this.imageKey]}.jpg`,
          complete: (res) => {
            count++;
            if (count == newList.length) this.initValue(idx);
          },
        });
        // #endif
      }
    },
    // 刷新
    refresh() {
      if (!this.isLoaded) {
        this.refreshDatas = this.value;
        return false;
      }
      setTimeout(() => {
        this.refreshDatas = [];
        this.isRefresh = true;
        this.adds = [];
        this.data.list = this.value ? this.value : [];
        this.data.column =
          this.column < 2
            ? 2
            : this.column >= this.maxColumn
            ? this.maxColumn
            : this.column;
        this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5;
        this.data.imageKey = this.imageKey;
        this.data.seat = this.seat;
        this.curIndex = 0;
        // 每列的数据初始化
        for (let i = 1; i <= this.data.column; i++) {
          this.data[`column_${i}_values`] = [];
          this.msg++;
        }
        this.$nextTick(() => {
          this.initValue(this.curIndex, "refresh==>");
        });
        this.recordDelId=''
      }, 1);
    },
    columnValue(index) {
      return this.data[`column_${index + 1}_values`];
    },
    change(newValue) {
      for (let i = 0; i < this.data.list.length; i++) {
        const cv = this.data[`column_${this.data.list[i].column}_values`];
        for (let j = 0; j < cv.length; j++) {
          if (newValue[i] && i === cv[j].index) {
            this.data[`column_${this.data.list[i].column}_values`][j] =
              Object.assign(cv[j], newValue[i]);
            this.msg++;
            break;
          }
        }
      }
    },
    getMin(a, s) {
      let m = a[0][s];
      let mo = a[0];
      for (var i = a.length - 1; i >= 0; i--) {
        if (a[i][s] < m) {
          m = a[i][s];
        }
      }
      mo = a.filter((i) => i[s] == m);
      return mo[0];
    },
    // 计算每列的高度
    getMinColumnHeight() {
      return new Promise((resolve) => {
        const heightArr = [];
        for (let i = 1; i <= this.data.column; i++) {
          const query = uni.createSelectorQuery().in(this);
          query
            .select(`#waterfalls_flow_column_${i}`)
            .boundingClientRect((data) => {
              heightArr.push({ column: i, height: data.height });
            })
            .exec(() => {
              if (this.data.column <= heightArr.length) {
                resolve(this.getMin(heightArr, "height"));
              }
            });
        }
      });
    },
    async initValue(i, from) {
      this.isLoaded = false;
      if (i >= this.data.list.length || this.refreshDatas.length) {
        this.msg++;
        this.loaded();
        return false;
      }
      const minHeightRes = await this.getMinColumnHeight();
      const c = this.data[`column_${minHeightRes.column}_values`];
      this.data.list[i].column = minHeightRes.column;
      c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 });
      this.msg++;
    },
    // 图片加载完成
    imgLoad(item, c) {
      const i = item.index;
      item.o = 1;
      this.$set(
        this.data[`column_${c}_values`],
        item.cIndex,
        JSON.parse(JSON.stringify(item))
      );
      this.initValue(i + 1);
    },
    // 图片加载失败
    imgError(item, c) {
      const i = item.index;
      item.o = 1;
      item[this.data.imageKey] = null;
      this.$set(
        this.data[`column_${c}_values`],
        item.cIndex,
        JSON.parse(JSON.stringify(item))
      );
      this.initValue(i + 1);
    },
    // 渲染结束
    loaded() {
      if (this.refreshDatas.length) {
        this.isLoaded = true;
        this.refresh();
        return false;
      }
      this.curIndex = this.data.list.length;
      if (this.adds.length) {
        this.data.list = this.adds[0];
        this.adds.splice(0, 1);
        this.initValue(this.curIndex);
      } else {
        if (this.data.list.length) this.$emit("loaded");
        this.isLoaded = true;
        this.isRefresh = false;
      }
    },
    // 单项点击事件
    itemClick(item) {
      // 判断是否存在删除遮罩
      if(this.recordDelType && this.existDel){
        return
      }
      
      // 存在商品下架提示不触发 显示删除按钮不触发
      if(!item[this.failKey] && item.id!==this.recordDelId){
        this.$emit("itemClick", item);
      }
    },
    // 图片点击事件
    imageClick(item) {
      if (this.touchEnd - this.touchStart < 150) {
        this.$emit("imageClick", item);
      }
      return null
    },
  },
  watch: {
    value: {
      deep: true,
      handler(newValue, oldValue) {
        setTimeout(() => {
          this.$nextTick(() => {
            if (this.isRefresh) return false;
            if (this.isLoaded) {
              // if (newValue.length <= this.curIndex) return this.refresh();
              if (newValue.length <= this.curIndex)
                return this.change(newValue);
              this.data.list = newValue;
              this.$nextTick(() => {
                this.initValue(this.curIndex, "watch==>");
              });
            } else {
              this.adds.push(newValue);
            }
          });
        }, 10);
      },
    },
    column(newValue) {
      this.refresh();
    },
  },
};
</script>
<style lang="scss" scoped>
.waterfalls-flow {
  overflow: hidden;

  &-column {
    float: left;
  }
}

.column-value {
  width: 100%;
  font-size: 0;
  overflow: hidden;
  transition: opacity 0.4s;
  opacity: 0;
  position: relative;
  &-show {
    opacity: 1;
  }

  .inner {
    font-size: 30rpx;
  }

  .img {
    border-radius: 16rpx 16rpx 0 0;
    width: 100%;
    &-hide {
      display: none;
    }

    &-error {
      background: #f2f2f2
        url()
        no-repeat center center;
    }
  }
}
.mask {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 99;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.53);
  border-radius: 10rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  &__text {
    width: 120rpx;
    height: 120rpx;
    background: #f12f22;
    border-radius: 50%;
    font-size: 28rpx;
    text-align: center;
    color: #ffffff;
    line-height: 120rpx;
    font-weight: bold;
  }
  &__tip {
    width: 170rpx;
    height: 170rpx;
    background: rgba(0, 0, 0, 0.51);
    border: 1px solid #ffffff;
    border-radius: 50%;
    font-size: 24rpx;
    text-align: center;
    color: #ffffff;
    line-height: 170rpx;
  }
}
</style>
